package com.cmw.core.security.xss;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.cmw.core.util.GenericsUtil;
import com.cmw.core.util.StringHandler;

public final class XssUtils {
	private static HTMLFilter xssFilter = HTMLFilter.getInstance();
	
	/**
	 * 将对象中的数据进行 xss 过滤
	 * @param obj	要过滤的对象
	 * @author chengmingwei
	 * @date 2015年4月9日 下午3:43:04
	 */
	public static <T> void filter(T obj){
		Class<?> cls = obj.getClass();
		Map<String,Field> fmaps = GenericsUtil.getAllFNames(cls);
		filter(obj, fmaps);
	}
	
	public static String filter(String val){
		if(!StringHandler.isValidStr(val)) return val;
		return xssFilter.filter(val);
	}
	
	/**
	 * 将对象中的所有属性值数据进行 xss 过滤
	 * @param obj	要过滤的对象
	 * @param excluseFields 不需要过虑的属性字段数组
	 * @author chengmingwei
	 * @date 2015年4月9日 下午3:43:04
	 */
	public static <T> void filter(T obj,String[] excluseFields){
		Class<?> cls = obj.getClass();
		Map<String,Field> fmaps = GenericsUtil.getAllFNames(cls);
		removeExcluseFields(excluseFields, fmaps);
		if(null == fmaps || fmaps.size() == 0) return;
		filter(obj, fmaps);
	}
	
	/**
	 * 将对象中的指定的属性值数据进行 xss 过滤，并排除不需要过滤的字段
	 * @param obj	要过滤的对象
	 * @param includeFields 要过滤的属性字段数组
	 * @param excluseFields 不需要过虑的属性字段数组
	 * @author chengmingwei
	 * @date 2015年4月9日 下午3:43:04
	 */
	public static <T> void filter(T obj,String[] includeFields,String[] excluseFields){
		Class<?> cls = obj.getClass();
		Map<String,Field> fmaps = GenericsUtil.getAllFNames(cls);
		removeExcluseFields(excluseFields, fmaps);
		fmaps = getIncludeFields(includeFields,fmaps);
		if(null == fmaps || fmaps.size() == 0) return;
		filter(obj, fmaps);
	}

	/**
	 * 将对象中的所有属性值数据进行 xss 过滤
	 * @param obj	要过滤的对象
	 * @param excluseFields 不需要过虑的属性字段数组
	 * @author chengmingwei
	 * @date 2015年4月9日 下午3:43:04
	 */
	public static <T> void filterTheFields(T obj,String[] includeFields){
		Class<?> cls = obj.getClass();
		Map<String,Field> fmaps = GenericsUtil.getAllFNames(cls);
		fmaps = getIncludeFields(includeFields,fmaps);
		if(null == fmaps || fmaps.size() == 0) return;
		filter(obj, fmaps);
	}
	
	private static Map<String,Field> getIncludeFields(String[] includeFields, Map<String,Field> fmaps){
		if(null == includeFields || includeFields.length == 0) return null;
		Map<String,Field> n_fmaps = new HashMap<String, Field>();
		for(String fieldName : includeFields){
			if(!fmaps.containsKey(fieldName)) continue;
			n_fmaps.put(fieldName, fmaps.get(fieldName));
		}
		return n_fmaps;
	}
	
	private static <T> void filter(T obj, Map<String, Field> fmaps) {
		Set<String> fieldNames = fmaps.keySet();
		for(String fieldName : fieldNames){
			Field field = fmaps.get(fieldName);
			Class<?> dataTypeCls = field.getType();
			String dataType = dataTypeCls.getSimpleName();
			if(!dataType.equals("String")) continue;
			field.setAccessible(true);
			Object val = null;
			try {
				val = field.get(obj);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
			if(null == val || "".equals(val)) continue;
			val = xssFilter.filter(val.toString());
			try {
				field.set(obj, val);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 从 fmaps 中删除 excluseFields 定义的字段
	 * @param excluseFields
	 * @param fmaps
	 * @author chengmingwei
	 * @date 2015年4月9日 下午3:51:14
	 */
	private static void removeExcluseFields(String[] excluseFields,Map<String,Field> fmaps){
		if((null == excluseFields || excluseFields.length == 0)
				||(null == fmaps || fmaps.size() == 0)) return;
		for(String fieldName : excluseFields){
			if(fmaps.containsKey(fieldName)) fmaps.remove(fieldName);
		}
	}
	
	
}

class Man{
	private String name;
	private String email;
	private String address;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
	
	
}
